<template>
  <div class="score-editor">
    <div class="score-header">
      <div class="score-meta">
        <div class="score-key-beat">
          <span>1={{score.key}}</span>
          <span class="score-beat">{{score.beat}}</span>
          <span class="score-tempo">J={{score.tempo}}</span>
        </div>
      </div>
      <div class="score-title-block">
        <div class="score-title" @click="editTitle = true" v-if="!editTitle">{{score.title}}</div>
        <input
          v-else
          v-model="titleInput"
          class="score-title-input"
          @blur="onTitleBlur"
          @keyup.enter="onTitleBlur"
        />
        <div class="score-subtitle" @click="editSubtitle = true" v-if="!editSubtitle">{{score.subtitle}}</div>
        <input
          v-else
          v-model="subtitleInput"
          class="score-subtitle-input"
          @blur="onSubtitleBlur"
          @keyup.enter="onSubtitleBlur"
        />
      </div>
      <div class="score-author-block">
        <div class="score-author" v-if="!editComposer" @click="editComposer = true">作曲：{{score.composer}}</div>
        <input
          v-else
          v-model="composerInput"
          class="score-author-input"
          @blur="onComposerBlur"
          @keyup.enter="onComposerBlur"
          placeholder="请输入作曲者"
        />
        <div class="score-lyricist" v-if="!editLyricist" @click="editLyricist = true">作词：{{score.lyricist}}</div>
        <input
          v-else
          v-model="lyricistInput"
          class="score-author-input"
          @blur="onLyricistBlur"
          @keyup.enter="onLyricistBlur"
          placeholder="请输入作词者"
        />
      </div>
    </div>
    <div class="score-body">
      <div class="score-watermark-group">
        <div v-for="(item, idx) in watermarkList" :key="idx" class="score-watermark"
          :style="{
            left: item.left + '%',
            top: item.top + '%',
            transform: `rotate(${item.rotate}deg)`,
            opacity: 0.3
          }"
        >{{score.copyright}}</div>
      </div>
      <div class="score-main-editor">
        <JianpuEditor 
          ref="jianpuEditor" 
          :currentSymbol="currentSymbol" 
          :currentChord="currentChord"
          :enableKeyboardPlayback="enableKeyboardPlayback" 
          :enableEdit="enableEdit"
          :showHighlight="showHighlight"
          @notePlayed="(note, cell) => $emit('notePlayed', note, cell)"
        />
      </div>
    </div>
  </div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
import ScoreStaffBlock from './ScoreStaffBlock.vue'
import { getDotInfoByPitchGroup, getNoteLineType, getUsedBeats } from '../utils/scoreUtils'
import JianpuEditor from './JianpuEditor.vue'
export default {
  name: 'ScoreEditor',
  components: { ScoreStaffBlock, JianpuEditor },
  props: {
    currentSymbol: {
      type: Object,
      default: () => ({ duration: '四分音符' })
    },
    currentChord: {
      type: String,
      default: null
    },
    enableKeyboardPlayback: {
      type: Boolean,
      default: false
    },
    enableEdit: {
      type: Boolean,
      default: false
    },
    showHighlight: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      editTitle: false,
      editSubtitle: false,
      editComposer: false,
      editLyricist: false,
      titleInput: '',
      subtitleInput: '',
      composerInput: '',
      lyricistInput: '',
      svgHeight: 800,
      rowHeight: 60,
      groupHeight: 160,
      measureSpacing: 180,
      noteSpacing: 36,
      measuresData: [
        { index: 1, notes: [[], []] } // 双声部默认，后续可根据scoreType动态调整
      ],
      watermarkList: []
    }
  },
  computed: {
    ...mapGetters(['scoreDraft']),
    score() {
      return this.scoreDraft
    },
    measures() {
      return this.score.measures && this.score.measures.length ? this.score.measures : this.measuresData
    },
    groupedMeasures() {
      const res = []
      for (let i = 0; i < this.measures.length; i += 4) {
        res.push(this.measures.slice(i, i + 4))
      }
      return res
    },
    svgWidth() {
      // 取每组最大小节数
      const maxGroupLen = Math.max(...this.groupedMeasures.map(g => g.length), 4)
      const leftWidth = 60
      const rightPadding = 60
      return leftWidth + maxGroupLen * this.measureSpacing + rightPadding
    },
    staffCount() {
      return this.score.scoreType === '双声部' ? 2 : 1;
    },
    isGrandStaff() {
      return this.score.scoreType === '双声部';
    }
  },
  watch: {
    'score.title'(val) {
      if (!this.editTitle) this.titleInput = val
    },
    'score.subtitle'(val) {
      if (!this.editSubtitle) this.subtitleInput = val
    },
    'score.composer'(val) {
      if (!this.editComposer) this.composerInput = val
    },
    'score.lyricist'(val) {
      if (!this.editLyricist) this.lyricistInput = val
    }
  },
  created() {
    this.titleInput = this.score.title
    this.subtitleInput = this.score.subtitle
    this.composerInput = this.score.composer
    this.lyricistInput = this.score.lyricist
    // 生成有规律的水印分布（网格排列）
    const rows = 4, cols = 4;
    const xStep = 100 / cols, yStep = 100 / rows;
    this.watermarkList = [];
    for (let r = 0; r < rows; r++) {
      for (let c = 0; c < cols; c++) {
        this.watermarkList.push({
          left: c * xStep + xStep / 2,
          top: r * yStep + yStep / 2,
          rotate: ((r + c) % 2 === 0 ? -20 : 20),
          opacity: 0.3
        });
      }
    }
  },
  methods: {
    ...mapActions(['setScoreDraft']),
    onTitleBlur() {
      this.editTitle = false
      if (this.titleInput !== this.score.title) {
        this.setScoreDraft({ title: this.titleInput })
      }
    },
    onSubtitleBlur() {
      this.editSubtitle = false
      if (this.subtitleInput !== this.score.subtitle) {
        this.setScoreDraft({ subtitle: this.subtitleInput })
      }
    },
    onComposerBlur() {
      this.editComposer = false
      if (this.composerInput !== this.score.composer) {
        this.setScoreDraft({ composer: this.composerInput })
      }
    },
    onLyricistBlur() {
      this.editLyricist = false
      if (this.lyricistInput !== this.score.lyricist) {
        this.setScoreDraft({ lyricist: this.lyricistInput })
      }
    },
    /**
     * 生成大括弧（花括号）SVG路径
     * @param {number} x 左上x
     * @param {number} y 左上y
     * @param {number} w 宽度
     * @param {number} h 高度
     * @returns {string}
     */
    bracePath(x, y, w, h) {
      // 近似花括号形状
      return `M${x+w/2},${y} Q${x},${y+h*0.2} ${x+w/2},${y+h*0.4} Q${x+w},${y+h*0.5} ${x+w/2},${y+h*0.6} Q${x},${y+h*0.8} ${x+w/2},${y+h}`
    },
    /**
     * 添加音符到指定小节和声部
     */
    addNote(measure, staffIdx) {
      const note = this.createNote();
      measure.notes[staffIdx].push(note);
      // 自动补小节
      if (this.shouldCreateNewMeasure(measure, staffIdx)) {
        this.addMeasure();
      }
    },
    /**
     * 创建新音符对象，结合当前符号工具栏的音高、时值
     */
    createNote() {
      // 这里可与符号工具栏联动，暂用默认
      const pitchGroup = this.selectedPitchGroup || '小字一组';
      const duration = this.selectedDuration || 1;
      const { dots, position } = getDotInfoByPitchGroup(pitchGroup);
      const lineType = getNoteLineType(duration);
      return {
        value: '', // 等用户输入
        dots,
        dotPosition: position,
        duration,
        lineType,
        verticalNotes: []
      };
    },
    /**
     * 判断是否需要新小节
     */
    shouldCreateNewMeasure(measure, staffIdx) {
      const used = getUsedBeats(measure, staffIdx);
      const maxBeats = this.getMaxBeats();
      return used >= maxBeats;
    },
    /**
     * 新增小节
     */
    addMeasure() {
      const index = this.measuresData.length + 1;
      const notes = Array.from({ length: this.staffCount }, () => []);
      this.measuresData.push({ index, notes });
    },
    /**
     * 音符输入事件
     */
    onNoteInput(measure, staffIdx, noteIdx, e) {
      // 录入数字，自动补点、时值等
      // 可判断是否需要自动补下一个音符或新小节
    },
    /**
     * 音符聚焦事件
     */
    onNoteFocus(measure, staffIdx, noteIdx) {
      // 可高亮当前音符，配合符号工具栏
    },
    /**
     * 双击音符，竖向叠加
     */
    onNoteDblClick(measure, staffIdx, noteIdx) {
      // 弹窗录入竖向音符
    },
    /**
     * 计算节拍上限
     */
    getMaxBeats() {
      const [beats] = this.score.beat.split('/').map(Number);
      return beats;
    },
    onPlayClick() {
      this.$refs.jianpuEditor && this.$refs.jianpuEditor.playScore && this.$refs.jianpuEditor.playScore();
    },
    initPiano() {
      this.piano = new Tone.Sampler({
        urls: {
          C4: "C4.mp3",
          "D#4": "Ds4.mp3",
          "F#4": "Fs4.mp3",
          A4: "A4.mp3"
          // ...更多音高
        },
        release: 1,
        baseUrl: "https://gleitz.github.io/midi-js-soundfonts/FluidR3_GM/acoustic_grand_piano-mp3/"
      }).toDestination();
    },
    onChordSelect(chord) {
      // 删除符号工具栏后，此方法不再需要
    }
  }
}
</script>
<style scoped>
.score-editor {
  width: 100%;
  height: 100%;
  padding: 32px 40px 40px 40px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
}
.score-header {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 32px;
}
.score-meta {
  min-width: 120px;
  text-align: left;
  font-size: 1.1rem;
  color: #333;
}
.score-key-beat span {
  display: block;
  margin-bottom: 4px;
}
.score-beat {
  font-size: 1.1rem;
  margin-left: 2px;
}
.score-tempo {
  font-size: 1.1rem;
  margin-left: 2px;
}
.score-title-block {
  flex: 1;
  text-align: center;
}
.score-title {
  font-size: 2rem;
  font-weight: 700;
  color: #222;
}
.score-subtitle {
  font-size: 1.1rem;
  color: #888;
  margin-top: 4px;
}
.score-author-block {
  min-width: 120px;
  text-align: right;
  font-size: 1rem;
  color: #333;
}
.score-body {
  flex: 1;
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
}
.score-watermark-group {
  position: absolute;
  left: 0; top: 0; right: 0; bottom: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}
.score-watermark {
  position: absolute;
  font-size: 2.2rem;
  color: #e0e0e0;
  user-select: none;
  pointer-events: none;
  font-weight: bold;
  white-space: nowrap;
  z-index: 0;
}
.score-sheet {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: 32px;
  margin-top: 40px;
}
.measure-block {
  min-width: 180px;
  background: #fff;
  border: 1px solid #eee;
  border-radius: 8px;
  padding: 24px 16px 16px 32px;
  position: relative;
  box-shadow: 0 2px 8px 0 rgba(0,0,0,0.04);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.measure-index {
  position: absolute;
  left: 8px;
  top: 4px;
  font-size: 12px;
  color: #888;
}
.staff-rows {
  display: flex;
  flex-direction: column;
  width: 100%;
  gap: 8px;
}
.staff-row {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 32px;
}
.note-cell {
  display: inline-block;
  position: relative;
  min-width: 32px;
  text-align: center;
}
.note-input {
  width: 28px;
  height: 32px;
  font-size: 20px;
  text-align: center;
  border: 1px solid #ddd;
  border-radius: 4px;
  outline: none;
}
.add-note-btn {
  margin-left: 8px;
  padding: 0 8px;
  height: 28px;
  font-size: 18px;
  border: none;
  background: #f5f7fa;
  border-radius: 4px;
  cursor: pointer;
}
.dots {
  font-size: 12px;
  color: #222;
  margin-left: 2px;
}
.dot {
  margin-left: 1px;
}
.tie-line {
  display: inline-block;
  width: 18px;
  height: 2px;
  background: #222;
  border-radius: 1px;
  margin-left: 2px;
  vertical-align: middle;
}
.underline-line {
  display: inline-block;
  width: 18px;
  height: 2px;
  background: #222;
  border-radius: 1px;
  margin-left: 2px;
  vertical-align: middle;
  border-bottom: 2px solid #222;
}
.vertical-notes {
  display: flex;
  flex-direction: column;
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
}
.vertical-note {
  font-size: 16px;
  color: #666;
}
.grand-brace {
  position: absolute;
  left: 0;
  top: 32px;
  font-size: 36px;
  color: #222;
  font-family: serif;
  font-weight: bold;
  line-height: 1;
}
.score-title-input {
  font-size: 2rem;
  font-weight: 700;
  text-align: center;
  width: 90%;
  margin: 0 auto 0.5rem auto;
  display: block;
  height: 48px;
  border: none;
  outline: none;
  background: transparent;
  box-shadow: none;
}
.score-title-input:focus {
  border: none;
  outline: none;
  background: transparent;
  box-shadow: none;
}
.score-subtitle-input {
  font-size: 1.3rem;
  text-align: center;
  width: 70%;
  margin: 0 auto 0.5rem auto;
  display: block;
  border: none;
  outline: none;
  background: transparent;
  box-shadow: none;
}
.score-subtitle-input:focus {
  border: none;
  outline: none;
  background: transparent;
  box-shadow: none;
}
.score-author-input {
  font-size: 1rem;
  text-align: right;
  width: 100%;
  margin: 0 0 0.5rem 0;
  display: block;
  border: none;
  outline: none;
  background: transparent;
  box-shadow: none;
  color: #333;
}
.score-author-input:focus {
  border: none;
  outline: none;
  background: transparent;
  box-shadow: none;
}
</style> 